package org.third.integration.kubernates.cmd.imp;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.third.common.utils.StreamUtils;
import org.third.integration.kubernates.cmd.KubectlCreate;
import org.third.integration.kubernates.cmd.imp.api.K8sApiBuilder;
import org.third.integration.kubernates.cmd.imp.bean.KubeInstanceInfo;
import org.third.integration.kubernates.cmd.imp.client.KubeRquestClient;
import org.third.integration.kubernates.cmd.imp.client.bean.ApiServerResponse;
import org.third.integration.kubernates.cmd.imp.exp.NotValidK8sYamlException;
import org.third.integration.kubernates.cmd.imp.exp.RequestApiServerException;
import org.third.integration.kubernates.cmd.imp.utils.K8S_TYPE_UTILS;

import com.esotericsoftware.yamlbeans.YamlException;
import com.esotericsoftware.yamlbeans.YamlReader;

@Component
public class KubeCreateImp implements KubectlCreate{
	
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private K8sApiBuilder k8sApiBuilder;
	
	@Autowired
	KubeRquestClient kubeRquestClient;
	
	@Override
	public KubeInstanceInfo execute(Reader reader) throws NotValidK8sYamlException, RequestApiServerException  {
		
		//verify yaml file
		KubeInstanceInfo kubeInstanceInfo = null;
		try{
			kubeInstanceInfo = validateYaml(reader);
		}finally{
			if(reader != null){
				try {
					reader.close();
				} catch (IOException e) {
					logger.warn("failed to close reader", e);
				}
			}
		}
		//create k8s instance
		kubeInstanceInfo = requestK8s(kubeInstanceInfo);
			
		return kubeInstanceInfo;
	}

	private KubeInstanceInfo requestK8s(KubeInstanceInfo kubeInstanceInfo) throws RequestApiServerException {
		String url = k8sApiBuilder.buildAPI(kubeInstanceInfo.getNamespace(), kubeInstanceInfo.getApiVersion(), kubeInstanceInfo.getType());
		logger.info("createurl:"+url);
		HttpPost httpPost = new HttpPost(url);
		httpPost.setHeader("Content-Type", "application/yaml");
		String yamlContent = kubeInstanceInfo.getYamlContent();
		//string转换成HTTPENTITY
		HttpEntity entity = new ByteArrayEntity(StreamUtils.stringToUtf8Bytes(yamlContent));
		httpPost.setEntity(entity);
		ApiServerResponse apiServerResponse = kubeRquestClient.requestK8s(httpPost);
		kubeInstanceInfo.setStatusCode(apiServerResponse.getStatusCode());
		kubeInstanceInfo.setResponseBody(apiServerResponse.getResponseBody());
		logger.info("apiServerResponse.getStatusCode():"+apiServerResponse.getStatusCode());
		logger.info("apiServerResponse.getResponseBody():"+apiServerResponse.getResponseBody());
		if(apiServerResponse.getException() != null){
			throw new RequestApiServerException("Failed to request API server", apiServerResponse.getException());
		}

		return kubeInstanceInfo;
	}


	private KubeInstanceInfo validateYaml(Reader reader)
			throws NotValidK8sYamlException {
		KubeInstanceInfo kubeInstanceInfo = null;
		//reader转换成string
		String yamlContent = StreamUtils.readerToString(reader);
		try {			
			//string转换成stringreader，stringreader转换成yamlreader
			YamlReader yamlReader = new YamlReader(new StringReader(yamlContent));
//			yamalreader可以读取字段的某个值
			Map map = (Map) yamlReader.read();
			String type = K8S_TYPE_UTILS.getType((String) map.get("kind"));
			String apiVersion = (String) map.get("apiVersion");
			String instanceName = (String) ((Map) map.get("metadata")).get("name");
			String namespace = (String) ((Map) map.get("metadata")).get("namespace");
			if(!K8S_TYPE_UTILS.getSpecificTypes().contains(type) && StringUtils.isEmpty(namespace)){
				throw new RuntimeException("namespace can't be empty ");
			}
			if(StringUtils.isEmpty(instanceName) || StringUtils.isEmpty(apiVersion) || StringUtils.isEmpty(type)){
				throw new RuntimeException("type or apiVersion or name can't be empty");
			}
			
			kubeInstanceInfo = new KubeInstanceInfo(type, apiVersion, instanceName, namespace, yamlContent);
		} catch (YamlException e) {
			throw new NotValidK8sYamlException("Failed to parse yaml: " + e.getCause().toString(), e);
		}
		catch (Exception e) {
			throw new NotValidK8sYamlException("Yaml validation failed before create kubernates instance.", e);
		}
		return kubeInstanceInfo;
	}
	
	@Override
	public KubeInstanceInfo execute(StringBuffer sb) throws NotValidK8sYamlException, RequestApiServerException {
		return this.execute(sb.toString());
	}

	@Override
	public KubeInstanceInfo execute(File file) throws NotValidK8sYamlException, RequestApiServerException {
		if(file == null || !file.exists()){
			throw new RuntimeException("File not found, file: " + file);
		}
		Reader reader = null;
		try {
			reader = new FileReader(file);
		} catch (FileNotFoundException e) {
			throw new RuntimeException("File not found", e);
		}
		return this.execute(reader);
	}

	@Override
	public KubeInstanceInfo execute(String content) throws NotValidK8sYamlException, RequestApiServerException  {
		Reader reader = new StringReader(content);
		return this.execute(reader);
	}

	@Override
	public KubeInstanceInfo execute(InputStream inputStream) throws NotValidK8sYamlException, RequestApiServerException {
		Reader reader = null;
		try {
			reader = new InputStreamReader(inputStream, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("Failed convert inputStream to reader", e);
		}
		return this.execute(reader);
	}

}
